package tagdb.ui;

import com.compomics.util.experiment.biology.Peptide;
import com.compomics.util.experiment.biology.ions.PeptideFragmentIon;
import com.compomics.util.experiment.identification.SpectrumAnnotator;
import com.compomics.util.experiment.identification.matches.IonMatch;
import com.compomics.util.experiment.identification.matches.PeptideMatch;
import com.compomics.util.experiment.massspectrometry.Charge;
import com.compomics.util.experiment.massspectrometry.MSnSpectrum;
import com.compomics.util.experiment.massspectrometry.Peak;
import com.compomics.util.experiment.massspectrometry.Precursor;
import com.compomics.util.gui.protein.ModificationProfile;
import com.compomics.util.gui.protein.SequenceModificationPanel;
import com.compomics.util.gui.spectrum.SpectrumPanel;
import com.compomics.util.preferences.AnnotationPreferences;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import no.uib.jsparklines.renderers.JSparklinesBarChartTableCellRenderer;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.JXTitledPanel;
import org.jfree.chart.plot.PlotOrientation;
import tagdb.algorithm.tag.Tag;
import tagdb.denovo.DenovoHit;
import tagdb.io.MascotGenericFile;
import tagdb.io.ModificationFile;
import tagdb.model.DenovoSearchResult;
import tagdb.model.ModifiedPeptide;
import tagdb.model.params.DenovoParams;
import tagdb.ui.filter.DenovoSearchFilter;
import tagdb.ui.util.PanelFactory;
import tagdb.ui.util.TableConfig;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.*;
import java.util.List;

public class ResultPanel extends JPanel {

    private JXTable spectraTbl;
    private JXTable denovoTbl;
    private JXTable tagsTbl;

    // Map containing the pepnovo hit results.
    private Map<String, List<DenovoHit>> resultsMap = new HashMap<String, List<DenovoHit>>();
    private List<MascotGenericFile> querySpectra;
    private DenovoSearchResult denovoSearchResult;
    private Map<String, Integer> titleToSpectrumMap = new HashMap<String, Integer>();
    private SpectrumPanel spectrumPanel;
    private JPanel spectrumJPanel;
    private MascotGenericFile selectedSpectrum;
    private Map<Integer, DenovoHit> denovoHits = new HashMap<Integer, DenovoHit>();
    private CellConstraints cc;
    private MainFrame mainFrame;
    private Peptide peptide;
    private JPanel spectrumOverviewPnl;
    private List<String> denovoTableToolTips;
    private List<String> spectraTableToolTips;
    private JButton tagViewBtn;
    private JXTitledPanel resultsPnl;
    private ArrayList<String> tagsTableToolTips;
    private JButton searchBtn;

    /**
     * Constructs the ResultPanel.
     * 
     * @param mainFrame 
     */
    public ResultPanel(MainFrame mainFrame) {
        this.mainFrame = mainFrame;
        initComponents();
    }

    /**
     * Initialize the components.
     */
    private void initComponents() {
        
        cc = new CellConstraints();

        // Build the spectrum overview panel
        spectrumOverviewPnl = new JPanel(new BorderLayout());
        spectrumJPanel = new JPanel();
        spectrumJPanel.setLayout(new BorderLayout());
        spectrumJPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
        spectrumJPanel.add(new SpectrumPanel(new double[]{0.0, 100.0}, new double[]{100.0, 0.0}, 0.0, "", ""));
        spectrumJPanel.setPreferredSize(new Dimension(100, 370));
        spectrumOverviewPnl.add(spectrumJPanel);
        
        JXTitledPanel specTtlPnl = PanelFactory.createTitledPanel("Spectrum Viewer", spectrumOverviewPnl);
        
        // Setup the tables
        setupSpectraTableProperties();
        setupDenovoTableProperties();
        setupTagsTableProperties();

        JScrollPane querySpectraTblPane = new JScrollPane(spectraTbl);
        querySpectraTblPane.setPreferredSize(new Dimension(430, 200));

        this.setLayout(new FormLayout("5dlu, p:g, 5dlu, p:g, 5dlu", "5dlu, f:p:g, 5dlu, f:p:g, 5dlu"));

        // Choose your spectra
        JPanel resultsSpectrumPnl = new JPanel();
        resultsSpectrumPnl.setLayout(new FormLayout("5dlu, p:g, 5dlu", "5dlu, t:p:g, 5dlu,"));
        resultsSpectrumPnl.add(querySpectraTblPane, cc.xy(2, 2));

        JXTitledPanel spectraPnl = PanelFactory.createTitledPanel("Query Spectra", resultsSpectrumPnl);

        // De novo results
        final CardLayout cardLayout = new CardLayout();
        final JPanel resultHitsPnl = new JPanel();
        final JPanel peptidePnl = new JPanel(new FormLayout("5dlu, p:g, 5dlu", "5dlu, t:p:g, 5dlu"));
        final JPanel tagsPnl = new JPanel(new FormLayout("5dlu, p:g, 5dlu", "5dlu, t:p:g, 5dlu"));
        resultHitsPnl.setLayout(cardLayout);

        resultHitsPnl.add(peptidePnl, "Peptides");
        resultHitsPnl.add(tagsPnl, "Tags");

        JScrollPane denovoHitsPane = new JScrollPane(denovoTbl);
        denovoHitsPane.setPreferredSize(new Dimension(570, 200));
        denovoHitsPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        denovoHitsPane.setToolTipText("Select denovo hits.");
        peptidePnl.add(denovoHitsPane, cc.xy(2, 2));

        JScrollPane tagsPane = new JScrollPane(tagsTbl);
        tagsPane.setPreferredSize(new Dimension(570, 200));
        tagsPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        tagsPane.setToolTipText("Select tags.");
        tagsPnl.add(tagsPane, cc.xy(2, 2));

        resultsPnl = PanelFactory.createTitledPanel("De Novo Peptide Hits", resultHitsPnl);
        searchBtn = new JButton("Find...");
        searchBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new FilterSpectraDialog(mainFrame, true);
            }
        });

        tagViewBtn = new JButton("Tag View");
        tagViewBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                cardLayout.previous(resultHitsPnl);
                Component[] components = resultHitsPnl.getComponents();
                for (Component component : components) {
                    if (component.isVisible()) {
                        if (component == peptidePnl) {
                            resultsPnl.setTitle("De Novo Peptide Hits");
                            tagViewBtn.setText("Tag View");
                        } else {
                            resultsPnl.setTitle("De Novo Tags");
                            tagViewBtn.setText("Peptide View");
                        }
                    }
                }
            }
        });
        spectraPnl.setRightDecoration(searchBtn);
        resultsPnl.setRightDecoration(tagViewBtn);

        this.add(specTtlPnl, cc.xyw(2, 2, 3));
        this.add(spectraPnl, cc.xy(2, 4));
        this.add(resultsPnl, cc.xy(4, 4));
    }

    /**
     * Shows the tag view.
     */
    private void showTagView() {
        // TODO: Fill de novo tag panel
        resultsPnl = PanelFactory.createTitledPanel("De Novo Tags", new JPanel());

        tagViewBtn = new JButton("Peptide View");
        resultsPnl.setRightDecoration(tagViewBtn);
    }
    
    /**
     * Display or hide the annotation menubar.
     */
    public void displayAnnotationMenu() {
        if (spectrumOverviewPnl.getComponentCount() == 2) {
            spectrumOverviewPnl.remove(1);
        }

        spectrumOverviewPnl.add(mainFrame.getAnnotationMenuBar(), BorderLayout.SOUTH);
    }

    /**
     * This method prepares the denovo hits table.
     */
    private void setupDenovoTableProperties() {

        final DefaultTableModel denovoTblMdl = new DefaultTableModel() {
            // instance initializer block
            {
                setColumnIdentifiers(new Object[]{"#", "Peptide", "RankScore", "Score", "N-Gap", "C-Gap", "m/z", "Charge"});
            }

            public boolean isCellEditable(int row, int col) {
                return false;
            }

            public Class<?> getColumnClass(int columnIndex) {
                switch (columnIndex) {
                    case 0:
                    case 7:
                        return Integer.class;
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                        return Double.class;
                    default:
                        return String.class;
                }
            }

        };

        denovoTableToolTips = new ArrayList<String>();
        denovoTableToolTips.add("Peptide Index");
        denovoTableToolTips.add("Peptide Sequence");
        denovoTableToolTips.add("Ranking Score");
        denovoTableToolTips.add("PepNovo Score of Peptide Sequence");
        denovoTableToolTips.add("Mass Gap from N-terminal to Sequence Start");
        denovoTableToolTips.add("Mass Gap from C-terminal to Sequence End");
        denovoTableToolTips.add("Peptide m/z");
        denovoTableToolTips.add("Peptide Charge");

        denovoTbl = new JXTable(denovoTblMdl) {
            protected JTableHeader createDefaultTableHeader() {
                return new JTableHeader(columnModel) {
                    public String getToolTipText(MouseEvent e) {
                        java.awt.Point p = e.getPoint();
                        int index = columnModel.getColumnIndexAtX(p.x);
                        int realIndex = columnModel.getColumn(index).getModelIndex();
                        String tip = (String) denovoTableToolTips.get(realIndex);
                        return tip;
                    }
                };
            }
        };


        // JSparklines for Scoring
        denovoTbl.getColumn("Score").setCellRenderer(new JSparklinesBarChartTableCellRenderer(PlotOrientation.HORIZONTAL, 100.0, new Color(110, 196, 97)));
        ((JSparklinesBarChartTableCellRenderer) denovoTbl.getColumn("Score").getCellRenderer()).showNumberAndChart(true, 50, new Font("Arial", Font.PLAIN, 12), 0);

        TableConfig.setColumnWidths(denovoTbl, new double[]{1, 10, 4, 8, 3, 3, 4, 3});
        TableColumnModel tcm = denovoTbl.getColumnModel();
        tcm.getColumn(0).setCellRenderer(new TableConfig.CustomTableCellRenderer(SwingConstants.RIGHT));

        // Sort the peptide table by the number of peptide hits
        denovoTbl.setAutoCreateRowSorter(true);

        // register list selection listener
        denovoTbl.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                refreshSpectrumPanel();
            }
        });

        // Single selection only
        denovoTbl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        denovoTbl.setSelectionBackground(new Color(130, 207, 250));

        // Add nice striping effect
        denovoTbl.addHighlighter(TableConfig.getSimpleStriping());

        // Column control
        denovoTbl.setColumnControlVisible(true);
    }

    /**
     * This method prepares the tags table.
     */
    private void setupTagsTableProperties() {

        final DefaultTableModel tagsTblMdl = new DefaultTableModel() {
            // instance initializer block
            {
                setColumnIdentifiers(new Object[]{"Rank", "Tag", "Type", "Score", "Charge"});
            }

            public boolean isCellEditable(int row, int col) {
                return false;
            }

            public Class<?> getColumnClass(int columnIndex) {
                switch (columnIndex) {
                    case 0:
                    case 4:
                        return Integer.class;
                    case 2:
                    case 3:
                        return Double.class;
                    default:
                        return String.class;
                }
            }

        };

        tagsTableToolTips = new ArrayList<String>();
        tagsTableToolTips.add("Tag Rank");
        tagsTableToolTips.add("Tag Sequence");
        tagsTableToolTips.add("Tag Type");
        tagsTableToolTips.add("Score");
        tagsTableToolTips.add("Tag Charge");

        tagsTbl = new JXTable(tagsTblMdl) {
            protected JTableHeader createDefaultTableHeader() {
                return new JTableHeader(columnModel) {
                    public String getToolTipText(MouseEvent e) {
                        java.awt.Point p = e.getPoint();
                        int index = columnModel.getColumnIndexAtX(p.x);
                        int realIndex = columnModel.getColumn(index).getModelIndex();
                        String tip = (String) tagsTableToolTips.get(realIndex);
                        return tip;
                    }
                };
            }
        };


        // JSparklines for Scoring
        tagsTbl.getColumn("Score").setCellRenderer(new JSparklinesBarChartTableCellRenderer(PlotOrientation.HORIZONTAL, 100.0, new Color(110, 196, 97)));
        ((JSparklinesBarChartTableCellRenderer) tagsTbl.getColumn("Score").getCellRenderer()).showNumberAndChart(true, 50, new Font("Arial", Font.PLAIN, 12), 0);

        TableConfig.setColumnWidths(tagsTbl, new double[]{1.5, 5, 5, 8, 3});
        TableColumnModel tcm = tagsTbl.getColumnModel();
        tcm.getColumn(0).setCellRenderer(new TableConfig.CustomTableCellRenderer(SwingConstants.RIGHT));

        // Sort the peptide table by the number of peptide hits
        tagsTbl.setAutoCreateRowSorter(true);

        // register list selection listener
        tagsTbl.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                refreshSpectrumPanel();
            }
        });

        // Single selection only
        tagsTbl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        tagsTbl.setSelectionBackground(new Color(130, 207, 250));

        // Add nice striping effect
        tagsTbl.addHighlighter(TableConfig.getSimpleStriping());

        // Column control
        tagsTbl.setColumnControlVisible(true);
    }

    /**
     * This method sets the spectra table up.
     */
    private void setupSpectraTableProperties() {
        // Query table
        final TableModel spectraTableMdl = new DefaultTableModel() {
            // instance initializer block
            {
                setColumnIdentifiers(new Object[]{"#", "Spectrum Title", "m/z", "Charge"});
            }

            public boolean isCellEditable(int row, int col) {
                return false;
            }

            public Class<?> getColumnClass(int columnIndex) {
                switch (columnIndex) {
                    case 0:
                    case 3:
                        return Integer.class;
                    case 2:
                        return Double.class;
                    default:
                        return String.class;
                }
            }
        };

        spectraTableToolTips = new ArrayList<String>();
        spectraTableToolTips.add("Spectrum Index");
        spectraTableToolTips.add("Spectrum Title");
        spectraTableToolTips.add("Spectrum Precursor m/z");
        spectraTableToolTips.add("Spectrum Precursor Charge");

        spectraTbl = new JXTable(spectraTableMdl) {
            protected JTableHeader createDefaultTableHeader() {
                return new JTableHeader(columnModel) {
                    public String getToolTipText(MouseEvent e) {
                        java.awt.Point p = e.getPoint();
                        int index = columnModel.getColumnIndexAtX(p.x);
                        int realIndex = columnModel.getColumn(index).getModelIndex();
                        String tip = (String) spectraTableToolTips.get(realIndex);
                        return tip;
                    }
                };
            }
        };
        
        TableConfig.setColumnWidths(spectraTbl, new double[]{1, 20, 5, 3});
        TableColumnModel tcm = spectraTbl.getColumnModel();
        tcm.getColumn(0).setCellRenderer(new TableConfig.CustomTableCellRenderer(SwingConstants.RIGHT));

        // Sort the peptide table by the number of peptide hits
        spectraTbl.setAutoCreateRowSorter(true);

        // register list selection listener
        spectraTbl.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                refreshSpectrumPanel();
                refreshDenovoTable();
                refreshTagsTable();
            }
        });

        // Single selection only
        spectraTbl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        spectraTbl.setSelectionBackground(TableConfig.ROW_SELECTION_BACKGROUND_COLOR);

        // Add striping effect
        spectraTbl.addHighlighter(TableConfig.getSimpleStriping());

        // Column control
        spectraTbl.setColumnControlVisible(true);
    }

    /**
     * Updates the spectrum panel.
     */
    public void refreshSpectrumPanel() {
        
        int row = spectraTbl.getSelectedRow();
        
        if (row != -1) {
            
            int spectrumID = (Integer) spectraTbl.getValueAt(row, spectraTbl.convertColumnIndexToView(0));
            selectedSpectrum = querySpectra.get(spectrumID - 1);
            
            // convert the spectrum
            ArrayList<Charge> precursorCharges = new ArrayList<Charge>();
            precursorCharges.add(new Charge(selectedSpectrum.getCharge(), Charge.PLUS));
            HashMap<Double,Peak> peakMap = new HashMap<Double, Peak>();
            HashMap<Double,Double> mgfPeaks = selectedSpectrum.getPeaks();
            Iterator<Double> iterator = mgfPeaks.keySet().iterator();
            while (iterator.hasNext()) {
                Double mass = iterator.next();
                peakMap.put(mass, new Peak(mass, mgfPeaks.get(mass)));
            }
            MSnSpectrum currentSpectrum = new MSnSpectrum(2, new Precursor(0.0, selectedSpectrum.getPrecursorMZ(), precursorCharges), "no title", peakMap, "no filename");

            spectrumPanel = new SpectrumPanel(
                            currentSpectrum.getMzValuesAsArray(), currentSpectrum.getIntensityValuesAsArray(),
                            selectedSpectrum.getPrecursorMZ(), selectedSpectrum.getCharge() + "+",
                            "", 40, false, false, false, 2, false);

            mainFrame.updateAnnotationMenus(selectedSpectrum.getCharge());

            // Update the annotations
            try {
                updateAnnotations();
            } catch (Exception e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(null, "An error occurred while updating the annotation.", "Annotation error", JOptionPane.ERROR_MESSAGE);
            }

            spectrumJPanel.removeAll();
            spectrumJPanel.add(spectrumPanel);
            spectrumJPanel.revalidate();
            spectrumJPanel.repaint();
        }
    }

    /**
     * Updates the annotations.
     */
    private void updateAnnotations() throws IOException, IllegalArgumentException, InterruptedException {
        int row = denovoTbl.getSelectedRow();
        if (row != -1) {
            //DenovoHit hit = denovoHits.get(denovoTbl.convertRowIndexToModel(row)); // @TODO: this only works if the table is no sorted!!
            DenovoHit hit = denovoHits.get(row);
            if (hit != null) {
                addAnnotations(hit);
            }
        }
    }

    /**
     * Update the denovo hit table based on the spectrum selected via mouse click.
     */
    private void refreshDenovoTable() {
        // Set the cursor into the wait status.
        this.setCursor(new Cursor(Cursor.WAIT_CURSOR));

        TableConfig.clearTable(denovoTbl);

        int row = spectraTbl.getSelectedRow();

        // Condition if one row is selected.
        if (row != -1) {

            String spectrumName = spectraTbl.getValueAt(row, 1).toString().trim();
            if (resultsMap.containsKey(spectrumName)) {
                List<DenovoHit> pepnovoList = resultsMap.get(spectrumName);

                for (int i = 0; i < pepnovoList.size(); i++) {
                    DenovoHit hit = pepnovoList.get(i);
                    ModifiedPeptide tempPeptide = hit.getPeptide();

                    Map<String, Color> map = new HashMap<String, Color>();
                    for(ModificationProfile profile : ModificationFile.getModificationProfile(tempPeptide)) {
                        map.put(profile.getPtmName(), profile.getColor());
                    }


                    if (hit != null) {
                        denovoHits.put(i, hit);

                        ((DefaultTableModel) denovoTbl.getModel()).addRow(new Object[]{
                                i + 1,
                                hit.getPeptide().getModifiedSequenceAsHtml(map, true),
                                hit.getRankScore(),
                                hit.getPepNovoScore(),
                                hit.getNTermGap(),
                                hit.getCTermGap(),
                                hit.getPrecursorMh(),
                                hit.getCharge()
                        });
                    }
                }
            }
            denovoTbl.getSelectionModel().setSelectionInterval(0, 0);
        }
        // Set the cursor back into the default status.
        this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }

    /**
     * Update the tags table based on the spectrum selected via mouse click.
     */
    private void refreshTagsTable() {
        // Set the cursor into the wait status.
        this.setCursor(new Cursor(Cursor.WAIT_CURSOR));

        TableConfig.clearTable(tagsTbl);

        int row = spectraTbl.getSelectedRow();

        // Condition if one row is selected.
        if (row != -1) {

            String spectrumName = spectraTbl.getValueAt(row, 1).toString().trim();
            if (denovoSearchResult.getTags(spectrumName) != null) {
                List<Tag> tags = denovoSearchResult.getTags(spectrumName);

                for (int i = 0; i < tags.size(); i++) {
                    Tag tag = tags.get(i);

                    if (tag != null) {
                        //denovoHits.put(i, hit);

                        ((DefaultTableModel) tagsTbl.getModel()).addRow(new Object[]{
                                i + 1,
                                tag.getSequence(),
                                tag.getType().name(),
                                tag.getScore(),
                                tag.getCharge()
                        });
                    }
                }
            }
            tagsTbl.getSelectionModel().setSelectionInterval(0, 0);
        }
        // Set the cursor back into the default status.
        this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }

    /**
     * Adds spectrum annotations based on the selected de novo hit.
     * 
     * @param hit 
     */
    private void addAnnotations(DenovoHit hit) throws IOException, IllegalArgumentException, InterruptedException {
        
        int row = spectraTbl.getSelectedRow();
        
        if (row != -1) {
            int spectrumID = (Integer) spectraTbl.getValueAt(row, spectraTbl.convertColumnIndexToView(0));
            selectedSpectrum = querySpectra.get(spectrumID - 1);
            
            // convert the spectrum
            ArrayList<Charge> precursorCharges = new ArrayList<Charge>();
            precursorCharges.add(new Charge(selectedSpectrum.getCharge(), Charge.PLUS));
            HashMap<Double,Peak> peakMap = new HashMap<Double, Peak>();
            HashMap<Double,Double> mgfPeaks = selectedSpectrum.getPeaks();
            Iterator<Double> iterator = mgfPeaks.keySet().iterator();
            while (iterator.hasNext()) {
                Double mass = iterator.next();
                peakMap.put(mass, new Peak(mass, mgfPeaks.get(mass)));
            }
            MSnSpectrum currentSpectrum = new MSnSpectrum(2, new Precursor(0.0, selectedSpectrum.getPrecursorMZ(), precursorCharges), "no title", peakMap, "no filename");

            // add the annotations
            SpectrumAnnotator spectrumAnnotator = new SpectrumAnnotator();

            // Get the annotation preferences
            AnnotationPreferences annotationPreferences = mainFrame.getAnnotationPreferences();

            // show annotated peaks in foreground, non-annotated in background
            spectrumPanel.showAnnotatedPeaksOnly(!annotationPreferences.showAllPeaks());

            // Set up the modified peptide
            ModifiedPeptide modifiedPeptide = hit.getPeptide();
            ArrayList<String> proteinList = new ArrayList<String>();
            proteinList.add("Dummy");
            Peptide currentPeptide = new Peptide(modifiedPeptide.getSequence(), proteinList, modifiedPeptide.getModificationMatches());
            
            // Get the de novo search parameters
            DenovoParams params = mainFrame.getDenovoParameters();
            annotationPreferences.setCurrentSettings(currentPeptide, hit.getCharge(), true);
            
            ArrayList<IonMatch> annotations = spectrumAnnotator.getSpectrumAnnotation(
                            annotationPreferences.getIonTypes(),
                            annotationPreferences.getNeutralLosses(),
                            annotationPreferences.getValidatedCharges(),
                            hit.getCharge(),
                            currentSpectrum, currentPeptide,
                            currentSpectrum.getIntensityLimit(0.0), // @TODO: should not be hardcoded?
                            params.getFragmentTol(),
                            false);

            spectrumPanel.setAnnotations(SpectrumAnnotator.getSpectrumAnnotation(annotations));
            
            // add de novo sequencing
            spectrumPanel.addAutomaticDeNovoSequencing(currentPeptide, annotations, 
                    PeptideFragmentIon.B_ION, // @TODO: Guess this might be b-ions and y-ions for forward and reverse ions derived from the de novo search engine (?)
                    PeptideFragmentIon.Y_ION, // @TODO: choose the reverse fragment ion type from the annotation menu bar!! (see question above)
                    annotationPreferences.getDeNovoCharge(),
                    annotationPreferences.showForwardIonDeNovoTags(),
                    annotationPreferences.showRewindIonDeNovoTags());

            mainFrame.updateAnnotationMenus(hit.getCharge());
        }
    }

    /**
     * This method updates the results in the panel.
     * 
     * @param denovoSearchResult
     */
    public void updateResults(DenovoSearchResult denovoSearchResult) {
        this.querySpectra = denovoSearchResult.getQuerySpectra();
        this.resultsMap = denovoSearchResult.getResultMap();
        this.denovoSearchResult = denovoSearchResult;

        // Update the spectra table.
        refreshSpectraTable();
    }

    /**
     * This method updates the spectra table with filtering parameters.
     */
    public void refreshFilteredSpectraTable(DenovoSearchFilter filter) {
        filter.setUnfilteredSpectra(querySpectra);
        filter.setResultsMap(resultsMap);

        // Retrieve the filtered spectra.
        List<MascotGenericFile> filteredSpectra = filter.getFilteredSpectra();
        for(MascotGenericFile mgf: filteredSpectra) {
            System.out.println(mgf.getTitle());
        }
        System.out.println(filteredSpectra.size());
        if(filteredSpectra.isEmpty()) {
            JOptionPane.showMessageDialog(mainFrame, "No results were found for the filter - no filtering applied.", "Filter warning", JOptionPane.WARNING_MESSAGE);
            return;
        }
        TableConfig.clearTable(spectraTbl);

        if (filteredSpectra != null) {
            for (int i = 0; i < filteredSpectra.size(); i++) {
                MascotGenericFile spectrum = filteredSpectra.get(i);
                String title = spectrum.getTitle();
                titleToSpectrumMap.put(title, i);
                ((DefaultTableModel) spectraTbl.getModel()).addRow(new Object[]{
                        i + 1,
                        title,
                        spectrum.getPrecursorMZ(),
                        spectrum.getCharge()
                });
            }
            spectraTbl.getSelectionModel().setSelectionInterval(0, 0);
        }
        refreshDenovoTable();
        refreshTagsTable();
    }
    /**
     * This method updates the spectra table.
     */
    private void refreshSpectraTable() {
        TableConfig.clearTable(spectraTbl);

        if (querySpectra != null) {
            for (int i = 0; i < querySpectra.size(); i++) {
                MascotGenericFile spectrum = querySpectra.get(i);
                String title = spectrum.getTitle();
                titleToSpectrumMap.put(title, i);
                ((DefaultTableModel) spectraTbl.getModel()).addRow(new Object[]{
                        i + 1,
                        title,
                        spectrum.getPrecursorMZ(),
                        spectrum.getCharge()
                });
            }
            spectraTbl.getSelectionModel().setSelectionInterval(0, 0);
        }
    }

    private void updateModificationProfile(PeptideMatch peptideMatch, boolean selectedPeptideProfile) {
        try {
            ArrayList<ModificationProfile> profiles = getModificationProfile(peptideMatch.getTheoreticPeptide());

            SequenceModificationPanel sequenceModificationPanel =
                    new SequenceModificationPanel(peptideMatch.getTheoreticPeptide().getNTerminal() + "-"
                            + peptideMatch.getTheoreticPeptide().getSequence()
                            + "-" + peptideMatch.getTheoreticPeptide().getCTerminal(),
                            profiles, true);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Returns the content of a Modification Profile cell for a desired peptide.
     *
     * @param peptide   The sequence of the peptide
     * @return          The modification profile
     */
    private ArrayList<ModificationProfile> getModificationProfile(Peptide peptide) {
        ArrayList<ModificationProfile> profiles = new ArrayList<ModificationProfile>();
        //Color ptmColor = peptideShakerGUI.getSearchParameters().getModificationProfile().getColor(ptmName);
        //ModificationProfile tempProfile = new ModificationProfile(ptmName, new double[peptide.getSequence().length()][2], ptmColor);
        return profiles;
    }



}

